package cn.dansj.common.utils.transfer;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class NameStyleUtils {
    /**
     * 命名格式枚举
     */
    public enum NamingFormat {
        LOWER_CAMEL_CASE,  // numberValue
        UPPER_CAMEL_CASE,  // NumberValue
        SNAKE_CASE,        // number_value
        UPPER_SNAKE_CASE,  // NUMBER_VALUE
        KEBAB_CASE,        // number-value
        DOT_CASE,          // number.value
        LOWER_CASE,        // numbervalue
        UNKNOWN            // 未知格式
    }

    /**
     * 检测字符串的命名格式
     *
     * @param input 要检测的字符串
     * @return 命名格式枚举值
     */
    public static NamingFormat detect(String input) {
        if (input == null || input.isEmpty()) {
            return NamingFormat.UNKNOWN;
        }
        // 检查顺序很重要，应该从最具体的模式开始
        if (isUpperSnakeCase(input)) {
            return NamingFormat.UPPER_SNAKE_CASE;
        }
        if (isSnakeCase(input)) {
            return NamingFormat.SNAKE_CASE;
        }
        if (isKebabCase(input)) {
            return NamingFormat.KEBAB_CASE;
        }
        if (isDotCase(input)) {
            return NamingFormat.DOT_CASE;
        }
        if (isUpperCamelCase(input)) {
            return NamingFormat.UPPER_CAMEL_CASE;
        }
        if (isLowerCamelCase(input)) {
            return NamingFormat.LOWER_CAMEL_CASE;
        }
        if (isLowerCase(input)) {
            return NamingFormat.LOWER_CASE;
        }

        return NamingFormat.UNKNOWN;
    }

    /**
     * 转换为指定格式
     *
     * @param input        输入字符串
     * @param targetFormat 目标格式
     * @return 转换后的字符串
     */
    public static String convertTo(String input, NamingFormat targetFormat) {
        NamingFormat sourceFormat = detect(input);

        if (sourceFormat == NamingFormat.UNKNOWN || targetFormat == NamingFormat.UNKNOWN) {
            return input;
        }
        if (sourceFormat == targetFormat) {
            return input;
        }
        // 先将输入字符串拆分为单词数组
        String[] words = splitToWords(input, sourceFormat);
        // 根据目标格式拼接单词
        return joinWords(words, targetFormat);
    }

    public static List<String> convertTo(String input) {
        List<String> words = new ArrayList<>();
        for (NamingFormat targetFormat : NamingFormat.values()) {
            words.add(convertTo(input, targetFormat));
        }
        return words;
    }

    // ========== 格式检测方法 ==========

    private static boolean isLowerCamelCase(String input) {
        return Pattern.matches("^[a-z][a-z0-9]*([A-Z][a-z0-9]*)+$", input);
    }

    private static boolean isUpperCamelCase(String input) {
        return Pattern.matches("^[A-Z][a-z0-9]*([A-Z][a-z0-9]*)*$", input);
    }

    private static boolean isSnakeCase(String input) {
        return Pattern.matches("^[a-z0-9]+(_[a-z0-9]+)+$", input);
    }

    private static boolean isUpperSnakeCase(String input) {
        return Pattern.matches("^[A-Z0-9]+(_[A-Z0-9]+)+$", input);
    }

    private static boolean isKebabCase(String input) {
        return Pattern.matches("^[a-z0-9]+(-[a-z0-9]+)+$", input);
    }

    private static boolean isDotCase(String input) {
        return Pattern.matches("^[a-z0-9]+(\\.[a-z0-9]+)+$", input);
    }

    private static boolean isLowerCase(String input) {
        return Pattern.matches("^[a-z0-9]+$", input);
    }

    // ========== 辅助方法 ==========

    private static String[] splitToWords(String input, NamingFormat sourceFormat) {
        switch (sourceFormat) {
            case LOWER_CAMEL_CASE:
            case UPPER_CAMEL_CASE:
                return input.split("(?=[A-Z])");
            case SNAKE_CASE:
            case UPPER_SNAKE_CASE:
                return input.split("_");
            case KEBAB_CASE:
                return input.split("-");
            case DOT_CASE:
                return input.split("\\.");
            default:
                return new String[]{input};
        }
    }

    private static String joinWords(String[] words, NamingFormat targetFormat) {
        if (words == null || words.length == 0) {
            return "";
        }

        switch (targetFormat) {
            case LOWER_CAMEL_CASE:
                StringBuilder lowerCamel = new StringBuilder(words[0].toLowerCase());
                for (int i = 1; i < words.length; i++) {
                    lowerCamel.append(capitalize(words[i]));
                }
                return lowerCamel.toString();
            case UPPER_CAMEL_CASE:
                StringBuilder upperCamel = new StringBuilder();
                for (String word : words) {
                    upperCamel.append(capitalize(word));
                }
                return upperCamel.toString();
            case SNAKE_CASE:
                return String.join("_", words).toLowerCase();
            case UPPER_SNAKE_CASE:
                return String.join("_", words).toUpperCase();
            case KEBAB_CASE:
                return String.join("-", words).toLowerCase();
            case DOT_CASE:
                return String.join(".", words).toLowerCase();
            case LOWER_CASE:
                return String.join("", words).toLowerCase();
            default:
                return String.join(" ", words);
        }
    }

    private static String capitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
    }

    // ========== 测试方法 ==========
    public static void main(String[] args) {
        String[] testCases = {
                "numberValue",    // LOWER_CAMEL_CASE
                "NumberValue",    // UPPER_CAMEL_CASE
                "number_value",   // SNAKE_CASE
                "NUMBER_VALUE",   // UPPER_SNAKE_CASE
                "number-value",   // KEBAB_CASE
                "number.value",   // DOT_CASE
                "numbervalue",    // LOWER_CASE
                "invalid Format"  // UNKNOWN
        };

        for (String testCase : testCases) {
            NamingFormat format = detect(testCase);
            System.out.printf("%-15s -> %-18s", testCase, format);

            // 转换为其他格式示例
            if (format != NamingFormat.UNKNOWN) {
                System.out.printf(" | to snake_case: %s",
                        convertTo(testCase, NamingFormat.SNAKE_CASE));
            }
            System.out.println();
        }

        // 格式转换示例
        String example = "userLoginCount";
        System.out.println("\nConversion examples:");
        System.out.println("Original: " + example);
        System.out.println("to snake_case: " + convertTo(example, NamingFormat.SNAKE_CASE));
        System.out.println("to UPPER_SNAKE_CASE: " + convertTo(example, NamingFormat.UPPER_SNAKE_CASE));
        System.out.println("to kebab-case: " + convertTo(example, NamingFormat.KEBAB_CASE));
        System.out.println("to dot.case: " + convertTo(example, NamingFormat.DOT_CASE));
        System.out.println("to UpperCamelCase: " + convertTo(example, NamingFormat.UPPER_CAMEL_CASE));
    }
}
